initial import boxroom 0.6.2
[boxroom-stian.git] / vendor / plugins / rubyzip-0.9.1 / lib / quiz1 / t / solutions / James Edward Gray II / solitaire.rb
bloba1650a9c6028fbd0ff97840e5cad3aaa2b1e04a2
1 #!/usr/bin/ruby -w
3 $deck = (1..52).to_a + ["A", "B"]               # Unkeyed deck - Keystream Step 1
5 def encrypt(message)
6         # Step 1
7         message = message.upcase.tr("^A-Z", "")
8         i = 5
9         while i < message.size
10                 message[i, 0] = " "
11                 i += 6
12         end
13         message += "X" while message.rindex(" ") != message.size - 6
14         
15         # Step 2
16         key_stream = generate(message.count("^ "))
17         
18         # Step 3
19         values = message.split("").map { |letter| letter[0] - ?A + 1 }
21         # Step 4
22         key_values = key_stream.split("").map { |letter| letter[0] - ?A + 1 }
23         
24         # Step 5
25         values.each_with_index do |value, index|
26                 next if value < 0
27                 values[index] = value + key_values[index]
28                 values[index] -= 26 if values[index] > 26
29         end
30         
31         # Step 6
32         message = (values.map { |number| (number - 1 + ?A).chr }).join("")
33         
34         return message
35 end
37 def decrypt(message)
38         # Step 1
39         key_stream = generate(message.size)
40         
41         # Step 2
42         values = message.split("").map { |letter| letter[0] - ?A + 1 }
44         # Step 3
45         key_values = key_stream.split("").map { |letter| letter[0] - ?A + 1 }
46         
47         # Step 4
48         values.each_with_index do |value, index|
49                 next if value < 0
50                 if value <= key_values[index]
51                         values[index] = value + 26 - key_values[index]
52                 else
53                         values[index] = value - key_values[index]
54                 end
55         end
56         
57         # Step 5
58         message = (values.map { |number| (number - 1 + ?A).chr }).join("")
59         
60         return message
61 end
63 def generate(count)             # Keystream Steps
64         key_stream = [ ]
66         until key_stream.size == count
67                 # Step 2
68                 a = $deck.index("A")
69                 if a == 53
70                         $deck.insert(1, $deck.pop)
71                 else
72                         $deck.insert(a + 1, $deck.delete_at(a))
73                 end
75                 # Step 3
76                 b = $deck.index("B")
77                 if b == 53
78                         $deck.insert(2, $deck.pop)
79                 elsif b == 52
80                         $deck.insert(1, $deck.delete_at(b))
81                 else
82                         $deck.insert(b + 2, $deck.delete_at(b))
83                 end
85                 # Step 4
86                 a = $deck.index("A")
87                 b = $deck.index("B")
88                 top = [a, b].min
89                 bottom = [a, b].max
90                 $deck = $deck.values_at((bottom + 1)..53, top..bottom, 0...top)
92                 # Step 5
93                 if $deck[53].kind_of? Integer
94                         $deck = $deck.values_at($deck[53]..52, 0...$deck[53], 53)
95                 end
97                 # Step 5
98                 if $deck[0].kind_of? Integer
99                         if $deck[$deck[0]].kind_of? Integer
100                                 key_stream.push($deck[$deck[0]])
101                         end
102                 else
103                         if $deck[53].kind_of? Integer
104                                 key_stream.push($deck[53])
105                         end
106                 end
107         end             # Step 7
109         key_stream.map! do |number|
110                 if number > 26
111                         (number - 26 - 1 + ?A).chr
112                 else
113                         (number - 1 + ?A).chr
114                 end
115         end
116         key_stream = key_stream.join("")
117         i = 5
118         while i < key_stream.size
119                 key_stream[i, 0] = " "
120                 i += 6
121         end
122         return key_stream
125 # Mind reading interface
126 if ARGV.size == 1 and ARGV[0] =~ /^(?:[A-Z]{5} )*[A-Z]{5}$/
127         puts decrypt(ARGV[0])
128 elsif ARGV.size == 1
129         puts encrypt(ARGV[0])
130 else
131         puts "Usage:  solitaire.rb MESSAGE"